<?php
    /*
    * @Author: KingMin 
    * @Date: 2021-07-13 19:55:29 
 * @Last Modified by: KingMin
 * @Last Modified time: 2021-07-13 20:28:35
    */
    /**
     * 基础函数库
     * @copyright (c) KINGMIN All Rights Reserved
     */
    // 自动加载类
    spl_autoload_register(function($class){
        // $c1=$class;
        $c1 = str_replace('\\', DIRECTORY_SEPARATOR, $class);
        $class = strtolower($class);
        if (file_exists(KINGMIN_ROOT . '/model/' . $class . '.php')) {
            require_once(KINGMIN_ROOT . '/model/' . $class . '.php');
        } elseif (file_exists(KINGMIN_ROOT . '/lib/' . $class . '.php')) {
            require_once(KINGMIN_ROOT . '/lib/' . $class . '.php');
        } elseif (file_exists(KINGMIN_ROOT . '/controller/' . $class . '.php')) {
            require_once(KINGMIN_ROOT . '/controller/' . $class . '.php');
        } elseif (file_exists(KINGMIN_ROOT . '/sdk/qiniuSdk/src/' . $c1 . '.php')) {
            require_once(KINGMIN_ROOT . '/sdk/qiniuSdk/src/' . $c1 . '.php');
        } elseif (file_exists(KINGMIN_ROOT . '/sdk/qiniuSdk/src/Qiniu/' . $c1 . '.php')) {
            require_once(KINGMIN_ROOT . '/sdk/qiniuSdk/src/Qiniu/' . $c1 . '.php');
        } elseif (file_exists(KINGMIN_ROOT . '/sdk/aliyunSdk/src/' . $c1 . '.php')) {
            require_once(KINGMIN_ROOT . '/sdk/aliyunSdk/src/' . $c1 . '.php');
        } elseif (file_exists(KINGMIN_ROOT . '/sdk/aliyunSdk/src/OSS/' . $c1 . '.php')) {
            require_once(KINGMIN_ROOT . '/sdk/aliyunSdk/src/OSS/' . $c1 . '.php');
        } elseif (file_exists(KINGMIN_ROOT .'/'. $c1 . '.php')) {
            require_once(KINGMIN_ROOT .'/'. $c1 . '.php');
        } elseif (file_exists(KINGMIN_ROOT.'/GatewayClient/' . $c1 . '.php')) {
            require_once(KINGMIN_ROOT .'/GatewayClient/' . $c1 . '.php');
        }else {
            kmMsg($class . '加载失败了。'.KINGMIN_ROOT .'/'. $c1 . '.php');
        }
    });
    // 返回格式
    function ajaxReturn ($state, $msg = '操作成功', $data = array()){
        $data = array(
            'code' => $state,
            'msg'   => $msg,
            'data'  => $data
        );
        die(json_encode($data, JSON_UNESCAPED_UNICODE));
    }
    // 返回格式
    function gatewayReturn ($state="300",$type="", $msg = '操作成功', $data = array(),$isjson=true){
        $data = array(
            'code' => $state,
            'type' => $type,
            'msg'   => $msg,
            'data'  => $data
        );
        if($isjson){
            return json_encode($data, JSON_UNESCAPED_UNICODE);
        }
        return $data;
    }
    // 返回格式
    function chatReturn ($state="300", $msg = '操作成功', $data = array()){
        $data = array(
            'code' => $state,
            'msg'   => $msg,
            'data'  => $data
        );
        return $data;
    }
    // 图片地址判断
    function imgUrlpd($img){
        if(!is_string($img)){
            return $img;
        }
        $new="";
        if($img==""){
            return $img;
        }
        if (substr($img,0, 2) === '//') {
            $new= $img;
        } elseif (substr($img,0, 4) === 'http') {
            $new= $img;
        } else {
            if(substr($img,0,1)==='/'){
                $img=substr($img,1);
            }
            if (substr(KINGMIN_URL, -1) === '/') {
                $new = KINGMIN_URL .$img;
            } else {
                $new = KINGMIN_URL . '/' . $img;
            }
        }
        return $new;
    }
    /**
     * 处理时间
     * 
     * @param string $s 转化好的时间
     * 
     * @return string $ftime 处理好的时间
     */
    function ftime($s){   
        $s=gmdate('H:i:s', $s); 
        $time = explode(':', $s);
        $time['0'] == '00' ? $h = 0 : $h = $time['0'];
        $time['1'] == '00' ? $m = 0 : $m = $time['1'];
        $time['2'] == '00' ? $s = 0 : $s = $time['2'];
        $ftime = (
        empty($h) ? (
            empty($m) ? $s .'秒' : (
                empty($s) ? $m . '分' : $m . '分' . $s .'秒'
                )
            ) :(
            empty($m) && empty($s) ? $h .'小时' : (
                empty($m)  ? $h . '时' . $s . '秒' : (
                    empty($s) ? $h . '小时' . $m . '分' : $h . '小时' . $m . '分' .$s . '秒'
                )
                    )
                        )
        );
        return $ftime;
    }
    /**
     * 计算两点之间的距离
     * @param $lng1 经度1
     * @param $lat1 纬度1
     * @param $lng2 经度2
     * @param $lat2 纬度2
     * @param int $unit m，km
     * @param int $decimal 位数
     * @return float
     */
    function getDistance($lng1, $lat1, $lng2, $lat2, $unit = 2, $decimal = 2)
    {
    
        $EARTH_RADIUS = 6370.996; // 地球半径系数
        $PI           = 3.1415926535898;
    
        $radLat1 = $lat1 * $PI / 180.0;
        $radLat2 = $lat2 * $PI / 180.0;
    
        $radLng1 = $lng1 * $PI / 180.0;
        $radLng2 = $lng2 * $PI / 180.0;
    
        $a = $radLat1 - $radLat2;
        $b = $radLng1 - $radLng2;
    
        $distance = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2)));
        $distance = $distance * $EARTH_RADIUS * 1000;
    
        if ($unit === 2) {
            $distance /= 1000;
        }
    
        return round($distance, $decimal);
    }
    // 替换图片地址
    function get_img_thumb_url($content=""){
    	preg_match_all('/<img(.*)src="([^"]+)"[^>]+>/isU',$content,$matches);
    	$img = "";
    	if(!empty($matches)) {
    		//注意，上面的正则表达式说明src的值是放在数组的第三个中
    		$img = $matches[2];
    	}else {
    		$img = "";
    	}
    	if (!empty($img)) {
    		//$img_url = $request->domain();
    		$img_url = KINGMIN_URL;
    		$patterns= array();
    		$replacements = array();
    		foreach($img as $imgItem){
    			if(stripos($imgItem,"http") === false)
    			{
    				$final_imgUrl = $img_url.$imgItem;
    				$replacements[] = $final_imgUrl;
    				$img_new = "/".preg_replace("/\//i","\/",$imgItem)."/";
    				$patterns[] = $img_new;
    			}
    		}
    		//让数组按照key来排序
    		ksort($patterns);
    		ksort($replacements);
    		//替换内容
    		$content = preg_replace($patterns, $replacements, $content);
    	}
    		return $content ;

    }
    /**
     * 验证输入的手机号码
     * @access  public
     * @param   string      $user_mobile      需要验证的手机号码
     * @return bool
     */
    function is_mobile($user_mobile=''){
        $chars = "/^((\(\d{2,3}\))|(\d{3}\-))?1(3|4|5|6|7|8|9)\d{9}$/";
        if (preg_match($chars, $user_mobile)){
            return true;
        }else{
            return false;
        }
    }
    // 验证用户名是否为字符串 //用户名正则，4到16位（字母)(数字，下划线，减号）/^[a-zA-Z0-9_-]{4,16}$/
    function is_uname($uname=''){
        $chars = "/^[a-zA-Z0-9_-]{4,16}$/";//"/^[a-zA-Z_]{4,16}$/";
        if (preg_match($chars, $uname)){
            return true;
        }else{
            return false;
        }
    }
    // 验证密码强度 //1.密码必须由字母、数字组成，区分大小写 2.密码长度为8-18位
    function is_password($pwd=''){
        if(mb_strlen($pwd,'UTF8')<8){
            return false;
        }
        $chars = "/^(?![^a-zA-Z]+$)(?!\D+$)/";
        if (preg_match($chars, $pwd)){
            return true;
        }else{
            return false;
        }
    }
    /**
     * 去除多余的转义字符
     */
    function doStripslashes() {
        $_GET = stripslashesDeep($_GET);
        $_POST = stripslashesDeep($_POST);
        $_COOKIE = stripslashesDeep($_COOKIE);
        $_REQUEST = stripslashesDeep($_REQUEST);
    }

    /**
     * 递归去除转义字符
     */
    function stripslashesDeep($value) {
        $value = is_array($value) ? array_map('stripslashesDeep', $value) : stripslashes($value);
        return $value;
    }

    /**
     * 转换HTML代码函数
     *
     * @param unknown_type $content
     * @param unknown_type $wrap 是否换行
     */
    function htmlClean($content, $nl2br = true) {
        $content = htmlspecialchars($content, ENT_QUOTES, 'UTF-8');
        if ($nl2br) {
            $content = nl2br($content);
        }
        $content = str_replace('  ', '&nbsp;&nbsp;', $content);
        $content = str_replace("\t", '&nbsp;&nbsp;&nbsp;&nbsp;', $content);
        return $content;
    }

    /**
     * 获取用户ip地址
     */
    function getIp() {
        $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
        if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
            $list = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            $ip = $list[0];
        }
        if (!ip2long($ip)) {
            $ip = '';
        }
        return $ip;
    }

    function makePregIP($str){
        if (stripos($str, "-") !== false) {
            $aIP = explode(".", $str);
            foreach ($aIP as $key => $value) {
                if (stripos($value, "-") === false) {
                    if ($key == 0) {
                        $preg_limit .= makePregIP($value);
                    } else {
                        $preg_limit .= '.' .makePregIP($value);
                    }
                } else {
                    $aipNum = explode("-", $value);
                    for ($i = $aipNum[0]; $i <= $aipNum[1]; $i++) {
                        $preg .= $preg ? "|" . $i : "[" . $i;
                    }
                    $preg_limit .= strrpos($preg_limit, ".", 1) == (strlen($preg_limit) - 1) ? $preg . "]" : "." . $preg . "]";
                }
            }
        } else {
            $preg_limit .= $str;
        }
        return $preg_limit;
    }

    function getAllBlockIP(){

            $blockips = Option::get('webscan_block_ip');
            if ($blockips) {
                $ip_array = explode(",", $blockips);
                foreach ($ip_array as $value) {
                    $ipaddress = makePregIP($value);
                    $ip = str_ireplace(".", "\.", $ipaddress);
                    $ip = str_replace("*", "[0-9]{1,3}", $ip);
                    $ipaddress = "/" . trim($ip) . "/";
                    $ip_list[] = $ipaddress;
                }
            }
            return $ip_list;
    }
    /**
     * 回复邮件通知
     */
    function   sendmail_do($mailserver, $port, $mailuser, $mailpass, $mailto, $subject,  $content, $fromname)
    {
        $mail = new SENDMAIL_PHPMailer();
        $mail->CharSet = "UTF-8";
        $mail->Encoding = "base64";
        $mail->Port = $port;

        if(MAIL_SENDTYPE == 1)
        {
            $mail->IsSMTP();
        }else{
            $mail->IsMail();
        }
        $mail->Host = $mailserver;
        $mail->SMTPAuth = true;
        $mail->Username = $mailuser;
        $mail->Password = $mailpass;

        $mail->From = $mailuser;
        $mail->FromName = $fromname;

        $mail->AddAddress($mailto);
        $mail->WordWrap = 500;
        $mail->IsHTML(true);
        $mail->Subject = $subject;
        $mail->Body = $content;
        $mail->AltBody = "This is the body in plain text for non-HTML mail clients";
        if($mail->Host == MAIL_SMTP) $mail->SMTPSecure = "ssl";
        if(!$mail->Send())
        {
            echo $mail->ErrorInfo;
            return false;
        }else{
            return true;
        }
    }
    /**
     * 获取站点地址(仅限根目录脚本使用,目前仅用于首页ajax请求)
     */
    function getUrl() {
        $phpself = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : '';
        if (preg_match("/^.*\//", $phpself, $matches)) {
            return '//' . $_SERVER['HTTP_HOST'] . $matches[0];
        } else {
            return KINGMIN_URL;
        }
    }

    /**
     * 获取当前访问的base url
     */
    function realUrl() {
        static $real_url = NULL;
        
        if ($real_url !== NULL) {
            return $real_url;
        }
        
        $emlog_path = PASH_ROOT . DIRECTORY_SEPARATOR;
        $script_path = pathinfo($_SERVER['SCRIPT_NAME'], PATHINFO_DIRNAME);
        $script_path = str_replace('\\', '/', $script_path);
        $path_element = explode('/', $script_path);
        
        $this_match = '';
        $best_match = '';
        
        $current_deep = 0;
        $max_deep = count($path_element);
        
        while($current_deep < $max_deep) {
            $this_match = $this_match . $path_element[$current_deep] . DIRECTORY_SEPARATOR;
            
            if (substr($emlog_path, strlen($this_match) * (-1)) === $this_match) {
                $best_match = $this_match;
            }
            
            $current_deep++;
        }
        
        $best_match = str_replace(DIRECTORY_SEPARATOR, '/', $best_match);
        $real_url  = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https://' : 'http://';
        $real_url .= $_SERVER["SERVER_NAME"];
        $real_url .= in_array($_SERVER['SERVER_PORT'], array(80, 443)) ? '' : ':' . $_SERVER['SERVER_PORT'];
        $real_url .= $best_match;
        
        return $real_url;
    }

    function isIE6Or7() {
        if (isset($_SERVER['HTTP_USER_AGENT'])) {
            if (stripos($_SERVER['HTTP_USER_AGENT'], "MSIE 7.0") || stripos($_SERVER['HTTP_USER_AGENT'], "MSIE 6.0")) {
                return true;
            }
        }
        return false;
    }

    /**
     * 验证email地址格式
     */
    function checkMail($email) {
        if (preg_match("/^[\w\.\-]+@\w+([\.\-]\w+)*\.\w+$/", $email) && strlen($email) <= 60) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 截取编码为utf8的字符串
     *
     * @param string $strings 预处理字符串
     * @param int $start 开始处 eg:0
     * @param int $length 截取长度
     */
    function subString($strings, $start, $length) {
        if (function_exists('mb_substr') && function_exists('mb_strlen')) {
            $sub_str = mb_substr($strings, $start, $length, 'utf8');
            return mb_strlen($sub_str, 'utf8') < mb_strlen($strings, 'utf8') ? $sub_str . '...' : $sub_str;
        }
        $str = substr($strings, $start, $length);
        $char = 0;
        for ($i = 0; $i < strlen($str); $i++) {
            if (ord($str[$i]) >= 128)
                $char++;
        }
        $str2 = substr($strings, $start, $length + 1);
        $str3 = substr($strings, $start, $length + 2);
        if ($char % 3 == 1) {
            if ($length <= strlen($strings)) {
                $str3 = $str3 .= '...';
            }
            return $str3;
        }
        if ($char % 3 == 2) {
            if ($length <= strlen($strings)) {
                $str2 = $str2 .= '...';
            }
            return $str2;
        }
        if ($char % 3 == 0) {
            if ($length <= strlen($strings)) {
                $str = $str .= '...';
            }
            return $str;
        }
    }

    /**
     * 从可能包含html标记的内容中萃取纯文本摘要
     *
     * @param string $data
     * @param int $len
     */
    function extractHtmlData($data, $len) {
        $data = subString(strip_tags($data), 0, $len + 30);
        $search = array("/([\r\n])[\s]+/", // 去掉空白字符
            "/&(quot|#34);/i", // 替换 HTML 实体
            "/&(amp|#38);/i",
            "/&(lt|#60);/i",
            "/&(gt|#62);/i",
            "/&(nbsp|#160);/i",
            "/&(iexcl|#161);/i",
            "/&(cent|#162);/i",
            "/&(pound|#163);/i",
            "/&(copy|#169);/i",
            "/\"/i",
        );
        $replace = array(" ", "\"", "&", " ", " ", "", chr(161), chr(162), chr(163), chr(169), "");
        $data = trim(subString(preg_replace($search, $replace, $data), 0, $len));
        return $data;
    }

    /**
     * 转换附件大小单位
     *
     * @param string $fileSize 文件大小 kb
     */
    function changeFileSize($fileSize) {
        if ($fileSize >= 1073741824) {
            $fileSize = round($fileSize / 1073741824, 2) . 'GB';
        } elseif ($fileSize >= 1048576) {
            $fileSize = round($fileSize / 1048576, 2) . 'MB';
        } elseif ($fileSize >= 1024) {
            $fileSize = round($fileSize / 1024, 2) . 'KB';
        } else {
            $fileSize = $fileSize . '字节';
        }
        return $fileSize;
    }

    /**
     * 获取文件名后缀
     */
    function getFileSuffix($fileName) {
        return strtolower(pathinfo($fileName,  PATHINFO_EXTENSION));
    }

    /**
     * 分页函数
     *
     * @param int $count 条目总数
     * @param int $perlogs 每页显示条数目
     * @param int $page 当前页码
     * @param string $url 页码的地址
     */
    function pages($pno,$pgs,$recordCount,$isAll=false){
        return $pages=[
            'isAll'=>$isAll?true:false,
            'recordCount' => $recordCount,     //满足条件的总记录数
            'pageSize' => $pgs,        //每页大小，即每页最多可以显示的记录数量
            'pageCount' =>  ceil($recordCount/$pgs),       //总页数
            'pno' => $pno,          //当前数据所在页号
        ];
    }

    /**
     * 文章分割
     *
     * @param string $content 文章内容
     * @param int $lid 文章id
     */
    function breakLog($content, $lid) {
        $ret = explode('[break]', $content, 2);
        if (!empty($ret[1])) {
            $ret[0].='<p class="readmore"><a href="' . Url::log($lid) . '">阅读全文&gt;&gt;</a></p>';
            return $ret[0];
        } elseif(Option::get('isexcerpt') == 'y') {
            return subString(trim(strip_tags($content)), 0, Option::get('excerpt_subnum')) . '<p class="readmore"><a href="' . Url::log($lid) . '">阅读全文&gt;&gt;</a></p>';
        } else {
            return $content;
        }
    }

    /**
     * 删除[break]标签
     *
     * @param string $content 文章内容
     */
    function rmBreak($content) {
        $content = str_replace('[break]', '', $content);
        return $content;
    }

    /**
     * 时间转化函数
     *
     * @param $now
     * @param $datetemp
     * @param $dstr
     * @return string
     */
    function smartDate($datetemp,$time=false) {
        $ptime= $datetemp;
        $etime = time() - $datetemp;
        if($time){
           if ($etime < 1) return date('G:s', $ptime);
           $interval = array (
                12 * 30 * 24 * 60 * 60 => date('y/n/j', $ptime),//一年
                30 * 24 * 60 * 60 => date('y/n/j', $ptime),//1个月
                7 * 24 * 60 * 60 => date('y/n/j', $ptime),//七天
                24 * 60 * 60 => (date('n/j', $ptime)),//天
                60 * 60 => date('G:i', $ptime),//小时
                60 => date('G:i', $ptime),//分钟
                1 => date('G:i', $ptime),
            ); 
            $wArr=[0=>"星期天",1=>"星期一",2=>"星期二",3=>"星期三",4=>"星期四",5=>"星期五",6=>"星期六"];
            foreach ($interval as $secs => $str) {
                $d = $etime / $secs;
                if ($d >= 1) {
                        $r = round($d);
                    if(60 * 60==$secs||24 * 60 * 60==$secs){
                        if(date('j', strtotime("+1 days",$ptime))==date('j')){
                           return "昨天 ".date('G:i', $ptime); 
                        }
                        $work=date('w', $ptime);
                        if(date('j', strtotime("+7 days",$ptime))>=date('j')){
                           return $wArr[$work]; 
                        }
                    }
                    return $str;
                }
            };
        }
        if ($etime < 1) return '刚刚';
        $interval = array (
            12 * 30 * 24 * 60 * 60 => '年前 ('.(date('Y-m-d', $ptime)).')',
            30 * 24 * 60 * 60 => '个月前 ('.(date('m-d', $ptime)).')',
            7 * 24 * 60 * 60 => '周前 ('.(date('m-d', $ptime)).')',
            24 * 60 * 60 => '天前',
            60 * 60 => '小时前',
            60 => '分钟前',
            1 => '秒前',
        );
        foreach ($interval as $secs => $str) {
            $d = $etime / $secs;
            if ($d >= 1) {
                $r = round($d);
            return $r . $str;
            }
        };
        
    }
    /**
     * 年龄转化函数
     *
     * @param $now
     * @param $datetemp
     * @param $dstr
     * @return string
     */
    function birthday($birthday){ 
        $age = strtotime($birthday); 
        $datetemp = strtotime($birthday); 
        if($age === false){ 
         return false; 
        } 
        list($y1,$m1,$d1) = explode("-",date("Y-m-d",$age)); 
        $now = strtotime("now"); 
        list($y2,$m2,$d2) = explode("-",date("Y-m-d",$now)); 
        $age = $y2 - $y1; 
        if((int)($m2.$d2) < (int)($m1.$d1)) 
         $age -= 1;
         
         $ptime= $datetemp;
         $etime = time() - $datetemp;
         if($age<1){
             $interval = array (
                30 * 24 * 60 * 60 => '个月',
                7 * 24 * 60 * 60 => '周',
                24 * 60 * 60 => '天'
            );
            foreach ($interval as $secs => $str) {
                $d = $etime / $secs;
                if ($d >= 1) {
                    $r = round($d);
                return $r . $str;
                }
            };
         }
        return $age.'岁'; 
    }
    function getAge($birthday) {
        $age = 0;
        
        $year = $month = $day = 0;
        
        if (is_array($birthday)) {
        extract($birthday);
        
        } else {
        if (stripos($birthday, '-') !== false) {
        list($year, $month, $day) = explode('-', $birthday);
        
        $day = substr($day, 0, 2); //get the first two chars in case of '2000-11-03 12:12:00'
        
        }
        
        }
        
        $age = date('Y') - $year;
        
        if (date('m') < $month || (date('m') == $month && date('d') < $day)) $age--;
        
        return $age;
    
    }

    /**
     * 生成一个随机的字符串
     *
     * @param int $length
     * @param boolean $special_chars
     * @return string
     */
    function getRandStr($length = 12, $special_chars = true) {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        if ($special_chars) {
            $chars .= '!@#$%^&*()';
        }
        $randStr = '';
        for ($i = 0; $i < $length; $i++) {
            $randStr .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $randStr;
    }

    /**
     * 寻找两数组所有不同元素
     */
    function findArray($array1, $array2) {
        $r1 = array_diff($array1, $array2);
        $r2 = array_diff($array2, $array1);
        $r = array_merge($r1, $r2);
        return $r;
    }

    /**
     * 计算时区的时差
     * @param string $remote_tz 远程时区
     * @param string $origin_tz 标准时区
     *
     */
    function getTimeZoneOffset($remote_tz, $origin_tz = 'UTC') {
        if ($origin_tz === null) {
            if (!is_string($origin_tz = date_default_timezone_get())) {
                return false; // A UTC timestamp was returned -- bail out!
            }
        }
        $origin_dtz = new DateTimeZone($origin_tz);
        $remote_dtz = new DateTimeZone($remote_tz);
        $origin_dt = new DateTime('now', $origin_dtz);
        $remote_dt = new DateTime('now', $remote_dtz);
        $offset = $origin_dtz->getOffset($origin_dt) - $remote_dtz->getOffset($remote_dt);
        return $offset;
    }

    /**
     * 获取指定月份的天数
     */
    function getMonthDayNum($month, $year) {
        $month = (int)$month;
        $year = (int)$year;
        
        $months_map = array(1=>31, 3=>31, 4=>30, 5=>31, 6=>30, 7=>31, 8=>31, 9=>30, 10=>31, 11=>30, 12=>31);
        if (array_key_exists($month, $months_map)) {
            return $months_map[$month];
        }
        else {
            if ($year % 100 === 0) {
                if ($year % 400 === 0) {
                    return 29;
                } else {
                    return 28;
                }
            }
            else if ($year % 4 === 0) {
                return 29;
            }
            else {
                return 28;
            }
        }
    }

    /**
     * zip压缩
     */
    function emZip($orig_fname, $content) {
        if (!class_exists('ZipArchive', FALSE)) {
            return false;
        }
        $zip = new ZipArchive();
        $tempzip = PASH_ROOT . '/content/cache/emtemp.zip';
        $res = $zip->open($tempzip, ZipArchive::CREATE);
        if ($res === TRUE) {
            $zip->addFromString($orig_fname, $content);
            $zip->close();
            $zip_content = file_get_contents($tempzip);
            unlink($tempzip);
            return $zip_content;
        } else {
            return false;
        }
    }

    /**
     * 获取远程文件
     * @param type $source 远程文件地址
     * @return 临时文件地址
     */
    function emFecthFile($source) {
        $temp_file = tempnam('/tmp', 'emtemp_');
        $rh = fopen($source, 'rb');
        $wh = fopen($temp_file, 'w+b');
        if ( ! $rh || ! $wh) {
            return FALSE;
        }

        while (!feof($rh)) {
            if (fwrite($wh, fread($rh, 4096)) === FALSE) {
                return FALSE;
            }
        }
        fclose($rh);
        fclose($wh);
        return $temp_file;
    }

    /**
     * 删除文件或目录
     */
    function emDeleteFile($file) {
        if (empty($file))
            return false;
        if (@is_file($file))
            return @unlink($file);
        $ret = true;
        if ($handle = @opendir($file)) {
            while ($filename = @readdir($handle)) {
                if ($filename == '.' || $filename == '..')
                    continue;
                if (!emDeleteFile($file . '/' . $filename))
                    $ret = false;
            }
        } else {
            $ret = false;
        }
        @closedir($handle);
        if (file_exists($file) && !rmdir($file)) {
            $ret = false;
        }
        return $ret;
    }

    /**
     * 页面跳转
     */
    function emDirect($directUrl) {
        header("Location: $directUrl");
        exit;
    }

/**
 * 显示系统信息
 *
 * @param string $msg 信息
 * @param string $url 返回地址
 * @param boolean $isAutoGo 是否自动返回 true false
 */
function kmMsg($msg, $url = 'javascript:history.back(-1);', $isAutoGo = false) {
    if ($msg == '404') {
        header("HTTP/1.1 404 Not Found");
        $msg = '抱歉，你所请求的页面不存在！';
    }
    echo <<<EOT
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN">
<head>
EOT;
    if ($isAutoGo) {
        echo "<meta http-equiv=\"refresh\" content=\"2;url=$url\" />";
    }
    echo <<<EOT
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>提示信息</title>
<style type="text/css">
<!--
body {
    background-color:#F7F7F7;
    font-family: Arial;
    font-size: 12px;
    line-height:150%;
}
.main {
    background-color:#FFFFFF;
    font-size: 12px;
    color: #666666;
    width:100%;
    max-width:650px;   
   /* sets max-width for IE */  
   _width:expression(document.body.clientWidth < 240 ? "240px" : "auto");   
    margin:60px auto 0px;
   border-radius: 0px;
   padding:30px 0px;
    list-style:none;
    border:#DFDFDF 1px solid;
}
.main p {
    line-height: 18px;
    margin: 5px 20px;
}
-->
</style>
</head>
<body>
<div class="main">
<p>$msg</p>
EOT;
    if ($url != 'none') {
        echo '<p><a href="' . $url . '">&laquo;点击返回</a></p>';
    }
    echo <<<EOT
</div>
</body>
</html>
EOT;
    exit;
}

/**
 * 显示404错误页面
 * 
 */
function show_404_page() {
    if (is_file(TEMPLATE_PATH . '404.php')) {
        header("HTTP/1.1 404 Not Found");
        include View::getView('404');
        exit;
    } else {
        kmMsg('404', KINGMIN_URL);
    }
}

    /**
     * hmac 加密
     *
     * @param unknown_type $algo hash算法 md5
     * @param unknown_type $data 用户名和到期时间
     * @param unknown_type $key
     * @return unknown
     */
    if(!function_exists('hash_hmac')) {
        function hash_hmac($algo, $data, $key) {
            $packs = array('md5' => 'H32', 'sha1' => 'H40');

            if (!isset($packs[$algo])) {
                return false;
            }

            $pack = $packs[$algo];

            if (strlen($key) > 64) {
                $key = pack($pack, $algo($key));
            } elseif (strlen($key) < 64) {
                $key = str_pad($key, 64, chr(0));
            }

            $ipad = (substr($key, 0, 64) ^ str_repeat(chr(0x36), 64));
            $opad = (substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64));

            return $algo($opad . pack($pack, $algo($ipad . $data)));
        }
    }

    /**
     * 根据文件后缀获取其mine类型
     * @param string $extension
     * @return string
     */
    function get_mimetype($extension) {
        $ct['htm'] = 'text/html';
        $ct['html'] = 'text/html';
        $ct['txt'] = 'text/plain';
        $ct['asc'] = 'text/plain';
        $ct['bmp'] = 'image/bmp';
        $ct['gif'] = 'image/gif';
        $ct['jpeg'] = 'image/jpeg';
        $ct['jpg'] = 'image/jpeg';
        $ct['jpe'] = 'image/jpeg';
        $ct['png'] = 'image/png';
        $ct['ico'] = 'image/vnd.microsoft.icon';
        $ct['mpeg'] = 'video/mpeg';
        $ct['mpg'] = 'video/mpeg';
        $ct['mpe'] = 'video/mpeg';
        $ct['qt'] = 'video/quicktime';
        $ct['mov'] = 'video/quicktime';
        $ct['avi'] = 'video/x-msvideo';
        $ct['wmv'] = 'video/x-ms-wmv';
        $ct['mp2'] = 'audio/mpeg';
        $ct['mp3'] = 'audio/mpeg';
        $ct['rm'] = 'audio/x-pn-realaudio';
        $ct['ram'] = 'audio/x-pn-realaudio';
        $ct['rpm'] = 'audio/x-pn-realaudio-plugin';
        $ct['ra'] = 'audio/x-realaudio';
        $ct['wav'] = 'audio/x-wav';
        $ct['css'] = 'text/css';
        $ct['zip'] = 'application/zip';
        $ct['pdf'] = 'application/pdf';
        $ct['doc'] = 'application/msword';
        $ct['bin'] = 'application/octet-stream';
        $ct['exe'] = 'application/octet-stream';
        $ct['class'] = 'application/octet-stream';
        $ct['dll'] = 'application/octet-stream';
        $ct['xls'] = 'application/vnd.ms-excel';
        $ct['ppt'] = 'application/vnd.ms-powerpoint';
        $ct['wbxml'] = 'application/vnd.wap.wbxml';
        $ct['wmlc'] = 'application/vnd.wap.wmlc';
        $ct['wmlsc'] = 'application/vnd.wap.wmlscriptc';
        $ct['dvi'] = 'application/x-dvi';
        $ct['spl'] = 'application/x-futuresplash';
        $ct['gtar'] = 'application/x-gtar';
        $ct['gzip'] = 'application/x-gzip';
        $ct['js'] = 'application/x-javascript';
        $ct['swf'] = 'application/x-shockwave-flash';
        $ct['tar'] = 'application/x-tar';
        $ct['xhtml'] = 'application/xhtml+xml';
        $ct['au'] = 'audio/basic';
        $ct['snd'] = 'audio/basic';
        $ct['midi'] = 'audio/midi';
        $ct['mid'] = 'audio/midi';
        $ct['m3u'] = 'audio/x-mpegurl';
        $ct['tiff'] = 'image/tiff';
        $ct['tif'] = 'image/tiff';
        $ct['rtf'] = 'text/rtf';
        $ct['wml'] = 'text/vnd.wap.wml';
        $ct['wmls'] = 'text/vnd.wap.wmlscript';
        $ct['xsl'] = 'text/xml';
        $ct['xml'] = 'text/xml';
        
        return isset($ct[strtolower($extension)]) ? $ct[strtolower($extension)] : 'text/html';
    }
    //获取浏览器类型
    function get_broswer(){ //获取浏览器类型
        $sys = $_SERVER['HTTP_USER_AGENT'];  //获取用户代理字符串
        if (stripos($sys, "Firefox/") > 0) {
            preg_match("/Firefox\/([^;)]+)+/i", $sys, $b);
            $exp[0] = "Firefox";
            $exp[1] = $b[1];  //获取火狐浏览器的版本号
        } elseif (stripos($sys, "Maxthon") > 0) {
            preg_match("/Maxthon\/([\d\.]+)/", $sys, $aoyou);
            $exp[0] = "傲游";
            $exp[1] = $aoyou[1];
        } elseif (stripos($sys, "MSIE") > 0) {
            preg_match("/MSIE\s+([^;)]+)+/i", $sys, $ie);
            $exp[0] = "IE";
            $exp[1] = $ie[1];  //获取IE的版本号
        } elseif (stripos($sys, "OPR") > 0) {
                preg_match("/OPR\/([\d\.]+)/", $sys, $opera);
            $exp[0] = "Opera";
            $exp[1] = $opera[1];  
        } elseif(stripos($sys, "Edge") > 0) {
            //win10 Edge浏览器 添加了chrome内核标记 在判断Chrome之前匹配
            preg_match("/Edge\/([\d\.]+)/", $sys, $Edge);
            $exp[0] = "Edge";
            $exp[1] = $Edge[1];
        } elseif (stripos($sys, "Chrome") > 0) {
                preg_match("/Chrome\/([\d\.]+)/", $sys, $google);
            $exp[0] = "Chrome";
            $exp[1] = $google[1];  //获取google chrome的版本号
        } elseif(stripos($sys,'rv:')>0 && stripos($sys,'Gecko')>0){
            preg_match("/rv:([\d\.]+)/", $sys, $IE);
                $exp[0] = "IE";
            $exp[1] = $IE[1];
        } elseif (stripos($sys, 'MicroMessenger')>0) {
                preg_match("/MicroMessenger\/([\d\.]+)/", $sys, $wx);
                $exp[0] = "微信浏览器";
                $exp[1] = $wx[1];
        } elseif (stripos($sys, 'AlipayClient')>0) {
                preg_match("/AlipayClient\/([\d\.]+)/", $sys, $zfb);
                $exp[0] = "支付宝浏览器";
                $exp[1] = $zfb[1];
        } elseif (stripos($sys, 'Safari')>0 || stripos($sys, 'iPhone')>0 || stripos($sys, 'Safari')>0 || stripos($sys, 'iPad')>0) {
                // preg_match("/AlipayClient\/([\d\.]+)/", $sys, $zfb);
                $exp[0] = "苹果浏览器";
                $exp[1] ="";
        }else {
            $exp[0] = "未知浏览器";
            $exp[1] = ""; 
        }
        return $exp[0].'('.$exp[1].')';
    }
    //获取操作系统类型
    function get_os(){
        $agent = $_SERVER['HTTP_USER_AGENT'];
        $os = false;
     
        if (preg_match('/win/i', $agent) && stripos($agent, '95'))
        {
          $os = 'Windows 95';
        }
        else if (preg_match('/win 9x/i', $agent) && stripos($agent, '4.90'))
        {
          $os = 'Windows ME';
        }
        else if (preg_match('/win/i', $agent) && preg_match('/98/i', $agent))
        {
          $os = 'Windows 98';
        }
        else if (preg_match('/win/i', $agent) && preg_match('/nt 6.0/i', $agent))
        {
          $os = 'Windows Vista';
        }
        else if (preg_match('/win/i', $agent) && preg_match('/nt 6.1/i', $agent))
        {
          $os = 'Windows 7';
        }
          else if (preg_match('/win/i', $agent) && preg_match('/nt 6.2/i', $agent))
        {
          $os = 'Windows 8';
        }else if(preg_match('/win/i', $agent) && preg_match('/nt 10.0/i', $agent))
        {
          $os = 'Windows 10';#添加win10判断
        }else if (preg_match('/win/i', $agent) && preg_match('/nt 5.1/i', $agent))
        {
          $os = 'Windows XP';
        }
        else if (preg_match('/win/i', $agent) && preg_match('/nt 5/i', $agent))
        {
          $os = 'Windows 2000';
        }
        else if (preg_match('/win/i', $agent) && preg_match('/nt/i', $agent))
        {
          $os = 'Windows NT';
        }
        else if (preg_match('/win/i', $agent) && preg_match('/32/i', $agent))
        {
          $os = 'Windows 32';
        }
        else if (preg_match('/linux/i', $agent))
        {
          $os = 'Linux';
        }
        else if (preg_match('/unix/i', $agent))
        {
          $os = 'Unix';
        }
        else if (preg_match('/sun/i', $agent) && preg_match('/os/i', $agent))
        {
          $os = 'SunOS';
        }
        else if (preg_match('/ibm/i', $agent) && preg_match('/os/i', $agent))
        {
          $os = 'IBM OS/2';
        }
        else if (preg_match('/Mac/i', $agent) && preg_match('/PC/i', $agent))
        {
          $os = 'Macintosh';
        }
        else if (preg_match('/PowerPC/i', $agent))
        {
          $os = 'PowerPC';
        }
        else if (preg_match('/AIX/i', $agent))
        {
          $os = 'AIX';
        }
        else if (preg_match('/HPUX/i', $agent))
        {
          $os = 'HPUX';
        }
        else if (preg_match('/NetBSD/i', $agent))
        {
          $os = 'NetBSD';
        }
        else if (preg_match('/BSD/i', $agent))
        {
          $os = 'BSD';
        }
        else if (preg_match('/OSF1/i', $agent))
        {
          $os = 'OSF1';
        }
        else if (preg_match('/IRIX/i', $agent))
        {
          $os = 'IRIX';
        }
        else if (preg_match('/FreeBSD/i', $agent))
        {
          $os = 'FreeBSD';
        }
        else if (preg_match('/teleport/i', $agent))
        {
          $os = 'teleport';
        }
        else if (preg_match('/flashget/i', $agent))
        {
          $os = 'flashget';
        }
        else if (preg_match('/webzip/i', $agent))
        {
          $os = 'webzip';
        }
        else if (preg_match('/offline/i', $agent))
        {
          $os = 'offline';
        }
        else
        {
          $os = '未知操作系统';
        }
        return $os;  
    }
    // 发送远程
    /**
     * $url 远程地址
     * $data 远程参数
     * **/
    function remote($url,$data) {
      $postdata = json_encode($data);
    //   return $postdata;
      $options = array(
        'http' => array(
          'method' => 'POST',
          'header' => "Content-type: application/json;charset=UTF-8\r\nAccept: application/json\r\nCache-Control: no-cache\r\nPragma: no-cache",
          'content' => $postdata,
          'timeout' => 15 * 60 // 超时时间（单位:s）
        )
      );
      $context = stream_context_create($options);
      @$result = file_get_contents($url, false, $context);
      $result=json_decode($result,true);
      return $result;
    }
    
    function url_exists($url) {
        $ch = curl_init(); 
        curl_setopt ($ch, CURLOPT_URL, $url); 
        //不下载
        curl_setopt($ch, CURLOPT_NOBODY, 1);
        //设置超时
        curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 3); 
        curl_setopt($ch, CURLOPT_TIMEOUT, 3);
        curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);  
        if($http_code == 200) {
            return true;
        }
        return false;
    }
    /**
    * 添加操作日志
    **/
    function addOperationLog($uid,$business_type,$operatorType='admin',$log_type,$log_title,$log_url,$log_data,$json_result,$status,$msg) {
        $DB = Database::getInstance();
        $log_ip=getIp();
        $location=ipToArea($log_ip);
        $log_browser=get_broswer();
        $log_os=get_os();
        $operator_type=getRequestFormType(false);
        if(!$operator_type){
            $operator_type=$operatorType;
        }
        $sql='INSERT INTO `'.DB_PREFIX.'sys_log_operation`(`uid`,`business_type`,`operator_type`,`log_type`, `log_title`,`log_url`,`log_data`,`log_ip`,`location`, `log_browser`, `log_os`, `json_result`,`status`,`log_msg`) VALUES("'.$uid.'","'.$business_type.'","'.$operator_type.'","'.$log_type.'","'.$log_title.'","'.$log_url.'","'.htmlspecialchars($log_data).'","'.$log_ip.'","'.$location.'","'.$log_browser.'","'.$log_os.'","'.htmlspecialchars($json_result).'","'.$status.'","'.htmlspecialchars($msg).'")';
        // return $sql;
        $DB->query($sql);
    }
    /**
    * 添加错误日志
    **/
    function addErrorLog($error_type,$log_data,$json_result,$msg="") {
        $DB = Database::getInstance();
        $log_ip=getIp();
        $location=ipToArea($log_ip);
        $log_browser=get_broswer();
        $log_os=get_os();
        $operator_type=getRequestFormType(false);
        if(!$operator_type){
            $operator_type="";
        }
        $sql='INSERT INTO `'.DB_PREFIX.'sys_log_error`(`operator_type`,`error_type`,`log_data`,`log_ip`,`location`, `log_browser`, `log_os`, `json_result`,`log_msg`) VALUES("'.$operator_type.'","'.$error_type.'","'.htmlspecialchars($log_data).'","'.$log_ip.'","'.$location.'","'.$log_browser.'","'.$log_os.'","'.htmlspecialchars($json_result).'","'.htmlspecialchars($msg).'")';
        // return $sql;
        $DB->query($sql);
    }
    /**
    * ip归属地查询
    **/
    function ipToArea($ip=""){
        if(!$ip){
            return '未知';
        }
        $api="http://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?query=".$ip."&co=&resource_id=6006";
        $ch = curl_init();
        curl_setopt($ch,CURLOPT_URL,$api);
        curl_setopt($ch,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_1);
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
        curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,3);
        $handles = curl_exec($ch);
        curl_close($ch);
        $handles= iconv('GB2312', 'UTF-8', $handles);
        $arr=json_decode($handles,true);
        @$location=$arr['data'][0]['location'];
        return $location;
    }
    //随机生成不重复的8位卡密
    function makeCardPassword($num=8){
        $num=intval($num);
        $code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $rand = $code[rand(0, 25)]
            . strtoupper(dechex(date('m')))
            . date('d') . substr(time(), -5)
            . substr(microtime(), 2, 5)
            . sprintf('%02d', rand(0, 99));
        for (
            $a = md5($rand, true),
            $s = '0123456789ABCDEFGHIJKLMNOPQRSTUV',
            $d = '',
            $f = 0;
            $f < $num;
            $g = ord($a[$f]),
            $d .= $s[($g ^ ord($a[$f + 8])) - $g & 0x1F],
            $f++
        ) ;
        return $d;
    }
    
    // 找出字符串中的电话
    
    function findThePhoneNumbers($oldStr = ""){
        $count = 0; //电话的个数
        // 检测字符串是否为空
        $oldStr=trim("q{$oldStr}q");
        $numbers = array();
        if(empty($oldStr)){
            return $numbers;
        }
        $strArr = explode("-", $oldStr);
        $newStr = $strArr[0];
        for ($i=1; $i < count($strArr); $i++) {
            if (preg_match("/\d{2}$/", $newStr) && preg_match("/^\d{11}/", $strArr[$i])){
                $newStr .= $strArr[$i];
            } elseif (preg_match("/\d{3,4}$/", $newStr) && preg_match("/^\d{7,8}/", $strArr[$i])) {
                $newStr .= $strArr[$i];
            } else {
                $newStr .= "-".$strArr[$i];
            }
        }
        // 手机号的获取
        $reg='/\D(?:86)?(\d{11})\D/is';//匹配数字的正则表达式
        preg_match_all($reg,$newStr,$result);
        return $result;
        $nums = array();
        $common = '/^1[3-9]\d{9}$/';
        foreach ($result[1] as $key => $value) {
            if(preg_match($common,$value)){
                $nums[] = $value;
            }
        }
        $count=count($nums);
        
        // 返回最终数组
        return $nums;
    }
    
    // 获取敏感词列表
    
    function sensitiveList(){
         global $CACHE;
        $sensitive_cache = $CACHE->readCache('sensitives');
        $list = array();
        $replaceArray = array();
        $sensitiveList = array();
        foreach ($sensitive_cache as $key => $v) {
            $list[]=$v['sname'];
            $replaceArray[$v['sname']]=$v['replace'];
            $sensitiveList[$v['sname']]=$v;
        }
        $data=[
            "sensitivecache"=>$sensitive_cache,
            "sensitiveList"=>$sensitiveList,
            "list"=>$list,
            "replaceArray"=>$replaceArray
            ];
        return $data;
    }
    
    // 敏感词判断
    function isSensitive($string){
        $data=sensitiveList();
        $rt=sensitive($data['list'], $string,$data['replaceArray']);
        $rt['send']=true;
        if($rt['count']>0){
             foreach ($rt['patternList'] as $k => $v) {
                $dt=$data['sensitiveList'][$v];
                if($dt['istype']=='2'){
                    $rt['send']=false;
                }
            }
        }
        return $rt;
    }
    
    /**
     * @todo 敏感词过滤，返回结果
     * @param array $list  定义敏感词一维数组
     * @param string $string 要过滤的内容
     * @return string replaceList 替换的数组
     * @return string $log 处理结果
     */
    function sensitive($list, $string,$replaceArray=""){
      $oldStr=trim("q{$string}q");
      $count = 0; //违规词的个数
      $sensitiveWord = '';  //违规词
      $stringAfter = $string;  //替换后的内容
      $pattern = "/".implode("|",$list)."/i"; //定义正则表达式
      if(preg_match_all($pattern, $string, $matches)){ //匹配到了结果
        $patternList = $matches[0];  //匹配到的数组
        $count = count($patternList);
        $sensitiveWord = implode(',', $patternList); //敏感词数组转字符串
        if(!$replaceArray){
            $replaceArray = array_combine($patternList,array_fill(0,count($patternList),'*')); //把匹配到的数组进行合并，替换使用["你妈"=>"nima","傻逼"=>"shabi","逼"=>"bi"];
        }
        $stringAfter = strtr($string, $replaceArray); //结果替换
      }
      
      $log=[
          "count"=>$count,
          "sensitiveWord"=>$sensitiveWord,
          "stringAfter"=>$stringAfter,
          "matches"=>$matches,
          "patternList"=>$patternList??[],
          "replaceArray"=>$replaceArray,
          ];
          
      return $log;
      
    }
    
    //对emoji表情转义
    function emoji_encode($str){
    	$strEncode = '';
    
    	$length = mb_strlen($str,'utf-8');
    
    	for ($i=0; $i < $length; $i++) {
    		$_tmpStr = mb_substr($str,$i,1,'utf-8');	
    		if(strlen($_tmpStr) >= 4){
    			$strEncode .= '[[EMOJI:'.rawurlencode($_tmpStr).']]';
    		}else{
    			$strEncode .= $_tmpStr;
    		}
    	}
    
    	return $strEncode;
    }
    //对emoji表情转反义
    function emoji_decode($str){
    	$strDecode = preg_replace_callback('|\[\[EMOJI:(.*?)\]\]|', function($matches){	
    		return rawurldecode($matches[1]);
    	}, $str);
    
    	return $strDecode;
    }
    
    //为上传的图片加上水印
	/*
	*自定义添加水印处理函数makeImageWaterMark
	*$image  上传的图片（要添加水印效果的图片资源标识）
	*$pos  水印位置
	*$water_text  水印文字
	*$font_size 水印文字大小
	*$color 水印文字颜色
	*/
	function makeImageWaterMark($image,$pos,$water_text,$font_size,$color){
		//获取TrueType字体
		$font_type = PASH_ROOT."/content/fonts/kaiti.ttf";
 
		//检查图片资源是否存在
		if (!empty($image) && file_exists($image))
		{
			//获取图像大小:返回一个具有四个单元的数组。索引 0 包含图像宽度的像素值，索引 1 包含图像高度的像素值。索引 2 是图像类型的标记：1 = GIF，2 = JPG，3 = PNG，4 = SWF，5 = PSD，6 = BMP，7 = TIFF(intel byte order)，8 = TIFF(motorola byte order)，9 = JPC，10 = JP2，11 = JPX，12 = JB2，13 = SWC，14 = IFF，15 = WBMP，16 = XBM。这些标记与 PHP 4.3.0 新加的 IMAGETYPE 常量对应。索引 3 是文本字符串，内容为“height="yyy" width="xxx"”，可直接用于 IMG 标记。
			$img_info = getimagesize($image);
			//获取背景图片的宽
			$g_w = $img_info[0];
			//获取背景图片的高
			$g_h = $img_info[1];
 
			//获取背景图片的格式
			switch ($img_info[2])
			{
				case 1:
					$img = imagecreatefromgif($image);
					break;
				
				case 2:
					$img = imagecreatefromjpeg($image);
					break;
 
				case 3:
					$img = imagecreatefrompng($image);
					break;
 
				default:
					die('图片格式错误！');
			}
		}
		else
		{
			ajaxReturn (300,'需要加水印的图片不存在！',$image); 
		}
 
		/*
		*获取使用TrueType 字体的文字的范围
		*array imagettfbbox ( float $size , float $angle , string $fontfile , string $text )
		*float $size   字体大小
		*float $angle  将被度量的角度大小
		*string $fontfile   水印文字字体
		*string $text  水印文字
		*/
		$temp = imagettfbbox(ceil($font_size*2.5),0,$font_type,$water_text);
		$w = $temp[2] - $temp[6];
		$h = $temp[3] - $temp[7];
 
		//判断水印文字大小是否超过图片大小
		if(($g_w<$w) || ($g_h<$h))
		{
			echo '需要添加水印的图片大小比水印文字区域小，无法生成水印！';
			return;
		}
 
 
		/*
		*设置10种水印效果位置
		*0：默认是随机位置
		*1：顶端居左
		*2：顶端居中
		*3：顶端居右
		*4：中部居左
		*5：中部居中
		*6：中部居右
		*7：底端居左
		*8：底端居中
		*9：底端居右
		*/
		switch ($pos) {
			case 0:
				$pos_x = rand(0,($g_w - $w));
				$pos_y = rand(0,($g_h - $h));
				break;
 
			case 1:
				$pos_x = 0;
				$pos_y = 0;
				break;
 
			case 2:
				$pos_x = ($g_w - $w) / 2;
				$pos_y = 0;
				break;
 
			case 3:
				$pos_x = $g_w - $w;
				$pos_y = 0;
				break;
 
			case 4:
				$pos_x = 0;
				$pos_y = ($g_h - $h) / 2;
				break;
 
			case 5:
				$pos_x = ($g_w - $w) / 2;
				$pos_y = ($g_h - $h) / 2;
				break;
 
			case 6:
				$pos_x = $g_w - $w;
				$pos_y = ($g_h - $h) / 2;
				break;
 
			case 7:
				$pos_x = 0;
				$pos_y = $g_h - $h;
				break;
 
			case 8:
				$pos_x = ($g_w -$w) / 2;
				$pos_y = $g_h -$h;
				break;
 
			case 9:
				$pos_x = $g_w - $w;
				$pos_y = $g_h - $h;
				break;
 
			default:
				$pos_x = rand(0,($g_w - $w));
				$pos_y = rand(0,($g_h - $h));
				break;
		}
 
		//设置图像混色模式
		imagealphablending($img, true);
 
 
		if(!empty($color) && (strlen($color)==7))
		{
			$R = hexdec(substr($color,1,2));
			$G = hexdec(substr($color,3,2));
			$B = hexdec(substr($color,5));
		}
 
		//为一幅图像分配颜色
		$text_color = imagecolorallocate($img, $R, $G, $B);
 
		//用 TrueType 字体向图像写入文本
		imagettftext($img, $font_size, 0, $pos_x, $pos_y, $text_color, $font_type, $water_text);
 
		//获取背景图的格式
		switch ($img_info[2])
		{
			case 1:
				imagegif($img,$image);
				break;
 
			case 2:
				imagejpeg($img,$image);
				break;
 
			case 3:
				imagepng($img,$image);
				break;
			
			default:
				die('不被支持格式的图片');
		}
        
        header('Content-Type: image/jpeg');
		imagedestroy($img);
	}
	/**
 * 格式化容量大小
 */
function format_size($size){
    if ($size >= 1073741824)
    {
        $size = round($size / 1073741824 * 100) / 100 . ' GB';
    }
    elseif ($size >= 1048576)
    {
        $size = round($size / 1048576 * 100) / 100 . ' MB';
    }
    elseif ($size >= 1024)
    {
        $size = round($size / 1024 * 100) / 100 . ' KB';
    }
    else
    {
        $size = $size . ' Bytes';
    }
 
    return $size;
}
// 获取请求类型
function getRequestFormType($type=false){
    @$formType=$_SERVER['HTTP_FORM_TYPE'];
    if(!$formType){
        if($type){
            ajaxReturn(404,"NOT FORM_TYPE");
        }else{
            return false;
        }
    }
    return $formType;
}
// 获取登录验证码
 function getcode($type='math',$key="",$dt=[]){
        // 获取code
        if($key){
            if($type=='math'){
                $code=CheckCode::getmathcode();
            }else{
                $code=CheckCode::getstrcode();
            }
            $w=120;$h=40;
            if(@$dt['w']){
                $w=$dt['w'];
            }
            if(@$dt['h']){
                $h=$dt['h'];
            }
            // ajaxReturn (404,'NoT KEY',$code['sum']); 
            $bclogintm=60*5;//5分钟
            if(!RedisService::op()){
                RedisService::init(3);//tonken  用户信息 uid_*
            }
            RedisService::setToken("code_".$key);
            $hccode=RedisService::getUser();
            if($hccode){
                RedisService::delUser("code_".$key);
                RedisService::setUser($hccode,$bclogintm);
                CheckCode::codeImg($hccode['code'],$w,$h,$type);
            }else{
                RedisService::setUser($code,$bclogintm);
                CheckCode::codeImg($code['code'],$w,$h,$type);
            }
        }else{
            ajaxReturn (404,'NoT KEY'); 
        }
        
        // return $code;
        // $cache->dir ="../../../content/mycache/checkcode/";
        // $cache->cacheFile =date("Y-m-d").".json";
    }
    // 验证code
    function iscodetrue($code,$key){
        if(!$code){return false; }
        if(!$key){return false; }
        
        if(!RedisService::op()){
            RedisService::init(3);//tonken  用户信息 uid_*
        }
        RedisService::setToken("code_".$key);
        $hccode=RedisService::getUser();
        if(!$hccode){
            ajaxReturn(500,'验证码已过期',$key);
        }
        if($hccode['sum']==strtoupper($code)){
            return true;
        }else{
            return false;
        }
    }
    // 获取短信验证码随机数
    function getSmsCode($phone){
        if($phone){
            
            $smsCode=rand(100000,999999);
            $bclogintm=60*5;//5分钟
            if(!RedisService::op()){
                RedisService::init(3);//tonken  用户信息 uid_*
            }
            RedisService::setToken("sms_".$phone);
            $hccode=RedisService::getUser();
            if($hccode){
                $tm=RedisService::ttl();
                if(($bclogintm-$tm)<60){
                    ajaxReturn (302,'请勿频繁发送,请等候'.(60-($bclogintm-$tm)).'秒再试!!!'); 
                }
                RedisService::delUser("sms_".$phone);
                RedisService::setUser($hccode,$bclogintm);
                return $hccode;
            }else{
                RedisService::setUser($smsCode,$bclogintm);
                return $smsCode;
            }
        }else{
            ajaxReturn (404,'NoT Phone'); 
        }
    }
    // 验证code
    function isSmscode($phone,$code){
        if(!$code){return false; }
        if(!$phone){return false; }
        
        if(!RedisService::op()){
            RedisService::init(3);//tonken  用户信息 uid_*
        }
        RedisService::setToken("sms_".$phone);
        $hccode=RedisService::getUser();
        if(!$hccode){
            ajaxReturn(500,'验证码不存在或者已过期',$code);
        }
        if($hccode==$code){
            return true;
        }else{
            return false;
        }
    }
    // 用户登录
    function signIn($dt){
        if(!$dt){
            ajaxReturn (404,"Missing request parameters" );//请求参数为空
        }
        if(@$dt['type']=='uname'){
            $opencode=intval(Option::get('isCode'));
            if($opencode){
                if(@!$dt['code']){
                    ajaxReturn(404,'请输入验证码',$dt);
                }
                if(@!$dt['codetype']){
                    ajaxReturn(404,'NoT CODEKEY',$dt);
                }
                $iscode=iscodetrue($dt['code'],$dt['codetype']);
                if(!$iscode){
                    ajaxReturn(500,'验证码不正确',$dt);
                }
            }
            $status=getRequestFormType(true);
            $os=[];
            if($status!='admin'){
                if(@$dt['os']){
                    @$os=$dt['os'];
                    $os['log_os']=$dt['os']['model'].'('.$dt['os']['system'].')';
                    $os['log_browser']=$dt['os']['hostName'].'('.$dt['os']['hostVersion'].')';
                }else{
                    ajaxReturn(404,'NOT OS',$dt);
                }
            }
            return loginAccountUser($dt['username'],$dt['password'],$os);
        }elseif(@$dt['type']=='phone'){
            return loginPhoneUser($dt);
        }else{
            ajaxReturn(505,'登录类型错误',$dt);
        }
        return ($dt);
    }
    // 发送手机验证码
    function phoneLoginSend($dt){
        if(Option::get("isSmsLogin")!='1'){
            ajaxReturn (100,'没有开启短信登录功能');
        }
        if(!@$dt['phone']){ajaxReturn (100,'手机号码不能为空');}
        if(!is_mobile(@$dt['phone'])){
            ajaxReturn (205,'手机号码格式不正确，请检查后提交',$dt);
        }
        $opencode=intval(Option::get('isCode'));
        
        if($opencode){
            if(@!$dt['code']){
                ajaxReturn(404,'请输入验证码',$dt);
            }
            if(@!$dt['codetype']){
                ajaxReturn(404,'NoT CODEKEY',$dt);
            }
            $iscode=iscodetrue($dt['code'],$dt['codetype']);
            if(!$iscode){
                ajaxReturn(500,'验证码不正确',$dt);
            }
        }
        $response=sendSmsCode($dt['phone']);
        $response= (array)$response;
		foreach ($response as $k => $v) {
		    if (gettype($v) == 'resource') {
		        return;
		    }
		    if (gettype($v) == 'object' || gettype($v) == 'array') {
		        $response[$k] = (array)object_to_array($v);
		    }
		}
        if(@$response['Code']!="OK"){
            ajaxReturn(300,'验证码发送失败',$response);
        }
        return $response;
        
    }
    // 发送验证码
    function sendSmsCode($phone=""){
        if(!is_mobile($phone)){
            ajaxReturn (205,'手机号码格式不正确，请检查后提交',$dt);
        }
        if(Option::get("isSms")=='1'){
            $smsCode=getSmsCode($phone);
            // ajaxReturn (200,'没有合适的短信运营商',$smsCode);
            if(Option::get('smsType')=='1'){
                if(!Option::get('aliy_sms_accessKeyId')||!Option::get('aliy_sms_secretKey')){
                    ajaxReturn (100,'请设置阿里云的相关信息');
                }
                $data=[
                    "phone"=>$phone,
                    "signName"=>Option::get('aliy_sms_signName'),
                    "templateCode"=>Option::get('aliy_sms_templateCode'),
                    "TemplateParam"=>json_encode(array(Option::get('aliy_sms_variable')=>$smsCode), JSON_UNESCAPED_UNICODE),
                ];
                // return $data;
                return Sms_Aliyun::sendSms($data);
            }
            ajaxReturn (100,'没有合适的短信运营商');
        }else{
            ajaxReturn (100,'短信服务没有开启');
        }
        
    }
    // 手机号码 $status 登录类型 1 为后台登录
    function loginPhoneUser($dt=[]){
        if(!@$dt['phone']){ajaxReturn (100,'用户手机号码不能为空');}
        if(!@$dt['code']){ajaxReturn (102,'短信验证码不能为空');}
        if(!is_mobile(@$dt['phone'])){
            ajaxReturn (205,'手机号码格式不正确，请检查后提交',$dt);
        }
        $iscode=isSmscode($dt['phone'],$dt['code']);
        if(!$iscode){
            ajaxReturn(500,'验证码不正确',$dt);
        }
        $status=getRequestFormType(true);
        $os=[];
        if($status!='admin'){
            if(@$dt['os']){
                @$os=$dt['os'];
                $os['log_os']=$dt['os']['model'].'('.$dt['os']['system'].')';
                $os['log_browser']=$dt['os']['hostName'].'('.$dt['os']['hostVersion'].')';
            }else{
                ajaxReturn(404,'NOT OS',$dt);
            }
        }
        $userData=LoginAuth::getPhoneDataByLogin($dt['phone']);
        if (false === $userData) {
            LoginAuth::addUserLoginLog(0,$dt['phone'],$dt['code'],2,'手机号不存在',$os,$dt['code']);
            ajaxReturn(301,'此手机没有绑定任何账号',$dt);
        }
        if($userData['isdel']!='0'){
            LoginAuth::addUserLoginLog($userData['uid'],$dt['phone'],$dt['code'],5,'账号已被删除',$os,$dt['code']);
            ajaxReturn(302,'此手机绑定的账号已被删除',$dt);
        }
        if($userData['status']!='0'){
            LoginAuth::addUserLoginLog($userData['uid'],$dt['phone'],$dt['code'],4,'账号被封禁',$os,$dt['code']);
            ajaxReturn(303,'此手机绑定的账号被封禁',$dt);
        }
        $user = LoginAuth::returnUser($userData);
        $string=htmlspecialchars($user['uid']).time().rand(100,999);
        // $user['token']=self::encrypt(json_encode($string),"E","KingMin");
        $user['token']=md5($string);
        $DB = Database::getInstance();
        $ipdz=getIp();
        $logdate=date("Y-m-d H:i:s");
        $sql=" UPDATE  `".DB_PREFIX."sys_member` SET `login_ip`='$ipdz',`login_date`='$logdate',`login_num`=login_num+1 WHERE `uid`='".$user['uid']."'";
        $DB->query($sql);
        LoginAuth::addUserLoginLog($user['uid'],$dt['phone'],$dt['code'],1,'手机短信登录成功',$os,$user['token'].' ；'.$dt['code']);
        
        loginCache($user);
    }
    
    // 账号密码登录 $status 登录类型 1 为后台登录
    function loginAccountUser($uname,$upwd,$dt=[]){
        if(!$uname){ajaxReturn (100,'用户名或手机号码不能为空');}
        if(!$upwd){ajaxReturn (102,'密码不能为空');}
        $dlcwcs1=intval(Option::get('dlcwcs1'));//登录错误超过限定次数,;
        $dlcwcs2=intval(Option::get('dlcwcs2'));//登录错误超过限定次数,;
        $dlcwdd1=intval(Option::get('dlcwdd1'));//登录错误超过限定次数 等到时长,单位秒;
        $dlcwdd2=intval(Option::get('dlcwdd2'));//登录错误超过限定次数 等到时长,单位秒;
        $dlpf=intval(Option::get('dlpf'));//登录登录频繁时长,单位秒;
        
        $ip="";
        if(intval(Option::get('dlippd'))==1){
            $ip=getIp().'';
        }
        $status=getRequestFormType(true);
        $login= new LoginAuth();
        $cache = new MyCache();
        $path=PASH_ROOT."/runtime/login/".$status.'/';
        $cache->dir =$path;//"../../../content/mycache/newadmin/";
        $cache->cacheFile ="loginerr.json";
        // return PASH_ROOT."/content/mycache/admin/loginerr.json";
        if($cache->getCache($uname.'<ip>'.$ip)){
            ajaxReturn (300,'登录频繁,请休息一下');
        }else{
            $cache->setCache($uname.'<ip>'.$ip,$upwd, $dlpf);
        }
        $cwcs=($cache->getCache($uname.'cw'));
        if($cwcs){
            if($cwcs<=$dlcwcs1){
                $dlcwcs=$dlcwcs1;
                $dlcwdd=$dlcwdd1;
            }else{
                $dlcwcs=$dlcwcs2;
                $dlcwdd=$dlcwdd2;
            }
            if($cwcs>=$dlcwcs){
                $sj1=(time())-($cache->getCache($uname.'cwtm'));
                $ddsc=$dlcwdd-$sj1;
                if($dlcwdd>$sj1){
                    $login->addUserLoginLog("",$uname,$upwd,5,'登录异常','登录异常,账号/密码错误'.$cwcs.'次,请等'.@ftime($ddsc));
                    ajaxReturn (302,'登录异常,账号/密码错误'.$cwcs.'次,请等'.@ftime($ddsc));
                }
            }
        }
        $lg = $login->checkUser($uname,$upwd,$dt,true);
        
        $cw=$cache->getCache($uname.'cw');
        if($cw){
            $cw+=1;
        }else{
            $cw=1;
        }
        if($lg===-1){
            $cache->setCache($uname.'cw',$cw, 86400);
            $cache->setCache($uname.'cwtm',time(), 86400);
            ajaxReturn (100,'账号错误');
        }elseif($lg===-2){
            $cache->setCache($uname.'cw',$cw, 86400);
            $cache->setCache($uname.'cwtm',time(), 86400);
            ajaxReturn (102,'密码错误');
        }elseif($lg===-4){
            ajaxReturn (103,'账号被封禁');
        }elseif($lg===-5){
            ajaxReturn (103,'账号不是管理员');
        }else{
            // $cache->cacheFile = "login.json";;
            $lg['avatar']=imgUrlpd($lg['avatar']);
            $lg['photo']=imgUrlpd($lg['photo']);
            // $cache->setCache($lg['token'], $lg['uid'], $bclogintm);
            
            $cache->cacheFile = "loginerr.json";
            $cache->removeCache($uname.'cw');
            $cache->removeCache($uname.'cwtm');
            $cache->removeCache($uname.'<ip>'.$ip);
            // 是否关闭后台 true 是 false 不关闭
            // $lg['issys']=ishtweihu( $lg['uid']);
            // RedisService::init();
            // RedisService::setToken($token);

            loginCache($lg);
            // ajaxReturn (500,'登录成功',$lg);
        }
        // return $isuname;
    }
    // 登录成功进行缓存
    function loginCache($user){
        $type=getRequestFormType(true);
        @$uid=$user['uid'];
        if(@$uid){
            if($type=='admin'){
                $bclogintm=intval(Option::get('bclogintm'));//保持登录状态的时间,单位小时;
                $bclogintm=$bclogintm*3600;
            }else{
                $bclogintm=intval(Option::get('webbclogintm'));//保持登录状态的时间,单位小时;
                $bclogintm=$bclogintm*86400;
            }
            $token=$user['token'];
            $user['time']=$bclogintm;
            if(!RedisService::op()){
                RedisService::init(3);//tonken  用户信息 uid_*
            }
            RedisService::setToken("token_".$token);
            RedisService::setUser($user,$bclogintm);
            
            $userTk="user_".$user['uid'];
            $user['userTk']=$userTk;
            RedisService::setToken($userTk);
            $rduser=RedisService::getUser();
            $loginTk=[
                "token"=>$token,
                "time"=>date("Y-m-d H:i:s"),
            ];
            if($rduser){
                @$user['login']=$rduser['login'];
                if(@$rduser['login'][$type]){
                    array_push($user['login'][$type],$loginTk);
                }else{
                    $user['login'][$type][]=$loginTk;
                }
                RedisService::delUser($userTk);
                // RedisService::setex($userTk,$user,$bclogintm);
                RedisService::setUser($user,$bclogintm);
            }else{
                $user['login'][$type][]=$loginTk;
                RedisService::setUser($user,$bclogintm);
            }
            ajaxReturn (200,'登录成功',$user);
        }else{
            ajaxReturn (400,'NoT Data',$user);
        }
    }
    // 判断用户是否在线
    function isUserOnLine($uid="",$ischat=false,$fix=""){
        if($uid){
            if(!RedisService::op()){
                RedisService::init(3);
            }
            $tkFix="user_";
            if($ischat){
                 $tkFix="webLogin_";
            }
            if($fix){
                 $tkFix=$fix;
            }
            
            $userTk=$tkFix.$uid;
            RedisService::setToken($userTk);
            $rduser=RedisService::getUser();
            if($rduser){
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }
    }
    // 获取登录用户信息
    function getLoginUser($type=false){
        @$token=$_SERVER['HTTP_AUTHORIZATION'];
        $lgtype=getRequestFormType(!$type);
        // if(RedisService::)
        if(!RedisService::op()){
            RedisService::init(3);
        }
        RedisService::setToken("token_".$token);
        $user=RedisService::getUser();
        if(!$user){
            if(!$type){
                ajaxReturn (410000,'没有登录信息',$token);
            }else{
                return false;
            }
        }else{
            @$userTk=($user['userTk']?$user['userTk']:$user['uid'])?"user_".$user['uid']:"";
            if(@!$userTk){
                if(!$type){
                    ajaxReturn (410003,'登录信息存在出问题',$user);
                }else{
                    return false;
                }
            }
        }
        RedisService::setToken($userTk);
        $rduser=RedisService::getUser();
        if(!$rduser){
            if(!$type){
                ajaxReturn (410000,'没有登录信息',$userTk);
            }else{
                return false;
            }
        }
        if(@$rduser['login'][$lgtype]){
            // if(in_array($token,$rduser['login']['admin'])){
            if(inArrayKeyFun("token",$token,$rduser['login'][$lgtype])){
                $rduser['token']=$token;
                return $rduser;
            // }elseif(in_array($token,$rduser['login']['adminout'])){
            }elseif(inArrayKeyFun("token",$token,$rduser['login'][$lgtype.'out'])){
                if(!$type){
                    ajaxReturn (410001,'登录已失效',$rduser);
                }else{
                    return false;
                }
            }else{
                if(!$type){
                    ajaxReturn (410002,'登录已过期',$rduser);
                }else{
                    return false;
                }
            }
        }else{
            if(!$type){
                ajaxReturn (410003,'登录信息存在出问题',$rduser);
            }else{
                return false;
            }
        }
    }
    // 更新用户缓存信息
    function userGenxin($uid=""){
        $login= new LoginAuth();
        if($uid){
            $newuser=$login->getLoginDetail($uid);
            @$userTk="user_".$uid;
            RedisService::setToken($userTk);
            $rduser=RedisService::getUser();
            $time=RedisService::ttl();
            if(!$rduser){
                return false;
            }
            $newuser['login']=$rduser['login'];
            RedisService::delUser($userTk);
            RedisService::setUser($newuser,$time);
            return $newuser;
        }else{
            @$token=$_SERVER['HTTP_AUTHORIZATION'];
            if(!RedisService::op()){
                RedisService::init(3);
            }
            RedisService::setToken("token_".$token);
            $user=RedisService::getUser();
            if(!$user){
                return false;
            }else{
                $uid=$user['uid'];
                $newuser=$login->getLoginDetail($uid);
                $time=RedisService::ttl();
                @$userTk=($user['userTk']?$user['userTk']:$user['uid'])?"user_".$user['uid']:"";
                if(@!$userTk){
                    return false;
                }else{
                    $newuser['userTk']=$userTk;
                    RedisService::delUser("token_".$token);
                    RedisService::setUser($newuser,$time);
                }
            }
            RedisService::setToken($userTk);
            $rduser=RedisService::getUser();
            $time=RedisService::ttl();
            if(!$rduser){
                return false;
            }
            $newuser['login']=$rduser['login'];
            RedisService::delUser($userTk);
            RedisService::setUser($newuser,$time);
            return $newuser;
        }
    }
    // 判断是否登录
    // $tyle 返回的值 false 返回数组或者弹窗 true 返回的值 true 或 false
    // 状态 410000=>没有登录信息,410001=>异地登录,410002=>登录已过期
    function isLogin($type=false){
        @$token=$_SERVER['HTTP_AUTHORIZATION'];
        $lgtype=getRequestFormType(!$type);
        if($lgtype=='admin'){
            $bclogintm=intval(Option::get('bclogintm'));//保持登录状态的时间,单位小时;
            $bclogintm=$bclogintm*3600;
        }else{
            $bclogintm=intval(Option::get('webbclogintm'));//保持登录状态的时间,单位小时;
            $bclogintm=$bclogintm*86400;
        }
        // if(RedisService::)
        if(!RedisService::op()){
            RedisService::init(3);
        }
        RedisService::setToken("token_".$token);
        $user=RedisService::getUser();
        if(!$user){
            if(!$type){
                ajaxReturn (410000,'没有登录信息',$token);
            }else{
                return false;
            }
        }else{
            @$userTk=($user['userTk']?$user['userTk']:$user['uid'])?"user_".$user['uid']:"";
            if(@!$userTk){
                if(!$type){
                    ajaxReturn (410003,'登录信息存在出问题$userTk-'.$userTk,$user);
                }else{
                    return false;
                }
            }else{
                RedisService::expire($bclogintm,"token_".$token);
            }
        }
        RedisService::setToken($userTk);
        $rduser=RedisService::getUser();
        if(!$rduser){
            if(!$type){
                ajaxReturn (410000,'没有登录信息',$userTk);
            }else{
                return false;
            }
        }
        if(@$rduser['login'][$lgtype]){
            // if(in_array($token,$rduser['login']['admin'])){
            if(inArrayKeyFun("token",$token,$rduser['login'][$lgtype])){
                RedisService::expire($bclogintm,$userTk);
                $rduser['token']=$token;
                return $rduser;
            // }elseif(in_array($token,$rduser['login']['adminout'])){
            }elseif(inArrayKeyFun("token",$token,$rduser['login'][$lgtype.'out'])){
                if(!$type){
                    ajaxReturn (410001,'登录已失效',$rduser);
                }else{
                    return false;
                }
            }else{
                if(!$type){
                    ajaxReturn (410002,'登录已过期',$rduser['login'][$lgtype]);
                }else{
                    return false;
                }
            }
        }else{
            if(!$type){
                ajaxReturn (410003,'登录信息存在出问题',$rduser);
            }else{
                return false;
            }
        }
    }
    // 退出登录
    function logOut(){
        @$token=$_SERVER['HTTP_AUTHORIZATION'];
        $lgtype=getRequestFormType(true);
        if(!RedisService::op()){
            RedisService::init(3);
        }
        RedisService::setToken("token_".$token);
        $user=RedisService::getUser();
        if(!$user){
            ajaxReturn (200,'退出成功',$token);
        }else{
            @$userTk=($user['userTk']?$user['userTk']:$user['uid'])?"user_".$user['uid']:"";
            if(@!$userTk){
                ajaxReturn (200,'退出成功',$token);
            }
        }
        RedisService::expire(0,"token_".$token); 
        RedisService::setToken($userTk);
        $rduser=RedisService::getUser();
        if(!$rduser){
            ajaxReturn (200,'退出成功',$token);
        }
        if(@$rduser['login'][$lgtype]){
            if(count($rduser['login'][$lgtype])>1){
                $newlogin=[];
                foreach($rduser['login'][$lgtype] as $k => $v){
                    if($v['token']!=$token){
                        $newlogin[]=$v;
                    }else{
                        $out=$v;
                    }
                }
                $out['outtime']=date("Y-m-d H:i:s");
                $rduser['login'][$lgtype]=$newlogin;
                $rduser['login'][$lgtype.'out'][]=$out;
                $time=RedisService::ttl();
                RedisService::delUser($userTk);
                RedisService::setUser($rduser,$time);
            }else{
               RedisService::expire(0,$userTk); 
            }
        }else{
            RedisService::expire(0,$userTk); 
        }
        $log_type="logout";
        $log_title="退出登录";
        $log_url='/'.$lgtype.'/logout';
        $log_data['token']=$token;
        $log_data=json_encode($log_data,JSON_UNESCAPED_UNICODE);
        $json_result=json_encode($rduser,JSON_UNESCAPED_UNICODE);
         $msg='用户【'.$rduser['nickName'].'】退出登录,成功';
        $caozuorz=addOperationLog($rduser['uid'],"0",$lgtype,$log_type,$log_title,$log_url,$log_data,$json_result,"0",$msg);
        ajaxReturn (200,'退出成功',$token);
    }
    // 判断某值是否在二维数组里面[["a"=>"b",["c"=>"d"],[["a"=>"b",["c"=>"d"]]]
    function inArrayKeyFun($k="",$v="",$arr=[]){
        $rt=false;
        if(empty($k)||empty($v)||empty($arr)){
            return $rt;
        }
        foreach($arr as $i => $d){
            if($d[$k]==$v){
                $rt=true;
            }
        }
        return $rt;
    }
    // 新增SQL转换
    function addSqlConvert($tb,$dt=[]){
        $kItem = array();
        $dItem = array();
        foreach ($dt as $key => $data) {
            if(!is_string($data)){
                $data=json_encode($data,JSON_UNESCAPED_UNICODE);
            }
            @$data=addslashes($data);
            $kItem[] = $key;
            $dItem[] = $data;
        }
        @$field ="`". implode("`,`", $kItem) . "`";
        @$values = "'" . implode("','", $dItem) . "'";
        $sql = " INSERT INTO `" . DB_PREFIX . $tb. "` ($field)VALUES($values); ";
        return $sql;
    }
    // 修改SQL转换
    function upSqlConvert($tb,$dt=[],$w){
        $Item = array();
        foreach ($dt as $key => $data) {
            if(!is_string($data)){
                $data=json_encode($data,JSON_UNESCAPED_UNICODE);
            }
            @$data=addslashes($data);
            $Item[] = "`$key`='$data'";
        }
        $upStr = implode(',', $Item);
        $sql = " UPDATE `" . DB_PREFIX . $tb . "` SET $upStr  WHERE $w ; ";
        return $sql;
    }
    
    /**
     * 判断两数组字符串是否相同用于 返回 修改过的数据
     * @param news 新数据
     * @param old 源数据
     * @istc 是否弹出 返回code true code else data     * 
     * @returns 返回 修改过的数据
     */
    function isModification($newArr=[],$oldArr=[],$istc=true,$code=""){
        // return $oldArr;
        $returnData =[];
        foreach($newArr as $k => $v){
            $news=$newArr[$k];
            $olds=$oldArr[$k]??"";
            if(!is_string($news)){
                $news=json_encode($news,JSON_UNESCAPED_UNICODE);
            }
            if(!is_string($olds)){
                $olds=json_encode($olds,JSON_UNESCAPED_UNICODE);
            }
            if($news!==$olds){
                $returnData["newData"][$k]=$newArr[$k];
                $returnData["modificationData"][$k]=$oldArr[$k]??"";
            }
        }
        if($istc){
            if(count($returnData)<=0){
                if(!$code){
                    $code=[
                        "code"=>201,
                        "msg"=>"没有要修改的数据,因为旧数据和新数据一样",
                        "data"=>["newData"=>$newArr,"old"=>$oldArr]
                    ];
                }
                ajaxReturn($code['code'],$code['msg'],$code['data']);
            }
        }
        return $returnData;
    }
    
    // 权限判读
    function isAuthority1($roleKey="",$menuName=""){
        if(!$roleKey||!$menuName){
            return false;
        }
        $db = Database::getInstance();
        $roleDateil=User_Model::getRoleDetailKey($roleKey);
        $list=User_Model::getRoleMenuList($roleDateil['role_id']);
        $list=$list['keys'];
        $query = $db->query("SELECT * FROM `".DB_PREFIX."sys_menu` where `menu_name`='$menuName' ; "); 
        $mid=0;
        while ($row = $db->fetch_array($query)) {
            $mid=$row['menu_id'];
        }
        if(in_array($mid,$list)){
            return true;
        }else{
            return false;
        }
    }
    // 从缓存中判断
    function isAuthority($roleKey="",$menuName=""){
        $CACHE=Cache::getInstance();
        $menu = $CACHE->readCache('menuRole');
        if(@$menu[$roleKey]){
            if(in_array($menuName,$menu[$roleKey])){
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }
    }
    
    // 判断是否为bool字符串,返true或false
    function isBoolStr($str=''){
        if(is_string($str)){
            if($str==='true'){
                return true;
            }else if($str==='false'){
                return false;
            }else if($str=='1'){
                return true;
            }else if($str=='0'){
                return false;
            }else{
                return $str;
            }
        }else{
            return $str;
        }
    }
    

    
    // 判断是否可以发送消息
    function isaddchat($dt){
        if(!is_array($dt)||!$dt){
            ajaxReturn(400,"参数为空",$dt);
        }
        
        $msg="包含电话号码";
        $text="";
        $issend=true;
        if($dt['type']=='text'){
            $text=$dt['payload']['text'];
            $phone=findThePhoneNumbers($text);
            
            $sensitive=isSensitive($text);
            if($sensitive['count']>0){
                $issend=$sensitive['send'];
                $text=$sensitive['stringAfter'];
                $msg="包含敏感词【".$sensitive['sensitiveWord']."】";
            }
        }
        $rddata=[
                "issend"=>$issend,
                "message"=>$dt,
                "istel"=>$phone,
                "text"=>$text,
                "msg"=>$msg,
                "sensitive"=>$sensitive,
                "list"=>sensitiveList()
            ];
        return $rddata;
    }
    
   
    
    
    
    
    
    
    
    
    
    
    
    
    